/*
 * Copyright (c) 2007 T.Cogghe, D.Leroux, S.Lévignac, S.Rives
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef __IMAGE_FINALE_H__
#define __IMAGE_FINALE_H__

#include "Image.hh"

class ImageFinale : public Image {
	private:
		double* pixels;
		int sz;
		double coef;	/* utilisé pour la conversion en unsigned char */


		int sat(double v) {
			unsigned int q=(int)(v*coef);
			if(q>=255) return 255;
			return q;
		}

		double* raw(int x, int y) const {
			return pixels+(y*p+x*pxsz);
		}

	public:
		ImageFinale(Image&i) : Image(i) {
			Image::Dark dark(&i);
			const unsigned char*src;
			double*dest;

			sz=i.largeur()*i.hauteur()*pxsz;
			pixels=new double[sz];
			for(int y=0;y<hauteur();y++) {
				for(int x=0;x<largeur();x++) {
					dest=raw(x,y);
					src=dark(x,y);
					dest[0]=src[0];
					dest[1]=src[1];
					dest[2]=src[2];
/*					if(Image::lum(src)>dark) {
						dest[0]=src[0];
						dest[1]=src[1];
						dest[2]=src[2];
					} else {
						dest[2]=dest[1]=dest[0]=0;
					}
*/
					
				}
			}
		}
		virtual ~ImageFinale() { if(pixels) delete pixels; }

		void majCoef(double nouveau) { coef=nouveau; maj(); }

		virtual unsigned char* operator() (int x, int y) const {
			if(x<0||x>=w||y<0||y>=h) {
				return NULL;
			}
			return px+(y*p+x*pxsz);
		}

		double calcCoefOptimal() {
			double max=0;
			for(int i=0;i<sz;i++) {
				if(max<pixels[i]) {
					max=pixels[i];
				}
			}
			if(max<1) {
				max=1;
			}

			coef=255./max;	/* maximiser sans saturation */

			maj();

			return coef;
		}

		ImageFinale&operator+=(Image&i) {
			Image::Dark dark(&i);
			const unsigned char*src;
			double*dest;
			for(int y=0;y<h;y++) {
				for(int x=0;x<w;x++) {
					if( (src=dark(x,y)) ) {
						dest=raw(x,y);
						dest[0]+=(double)src[0];
						dest[1]+=(double)src[1];
						dest[2]+=(double)src[2];
					}
/*					if( (src=i(x,y)) && Image::lum(src)>dark ) {
						dest=raw(x,y);
						dest[0]+=(double)src[0];
						dest[1]+=(double)src[1];
						dest[2]+=(double)src[2];
					}
*/
				}
			}
			return *this;
		}

		void maj() {
			unsigned char*dest;
			double*src;
			for(int y=0;y<hauteur();y++) {
				for(int x=0;x<largeur();x++) {
					src=raw(x,y);
					dest=(*this)(x,y);
					dest[0]=sat(src[0]);
					dest[1]=sat(src[1]);
					dest[2]=sat(src[2]);
				}
			}
		}
};

#endif
